<template>
<div>
  <el-upload
    name="file"
    :headers="headers"
    class="avatar-uploader"
    :before-upload="beforeAvatarUpload"
    :action="api"
    ref="uploadFile"
    drag
    :show-file-list="false"
    :on-success="handlePicUploadSuccess"
    :on-error="handlePicUploadError"
    :disabled="disabledStrPri"
  >
    <div class="avatar avatar-wrap" v-if="valuePri">
      <div class="avatar">
        <div class="avatar-img" :style="{'backgroundImage':`url(${valuePri})`}"></div>
      </div>
      <div class="hover-avatar" @click="hoverAvatarClick">
        <span class="preview" @click="handlePictureCardPreview"><el-icon><View /></el-icon></span>
        <span v-if="!isPreview" class="delete" @click="handlePictureCardDelete"><el-icon><Delete /></el-icon></span>
      </div>
    </div>
    <div v-else>
      <div v-if="uploading" v-loading="uploading" class="avatar-uploader-icon"></div>
      <div v-if="!uploading" class="avatar-uploader-icon">
        <div class="up-icon">
          <span>
            <el-icon><CirclePlusFilled /></el-icon>
          </span>
          <span>
            <i>将图片拖至此处，或</i>
            <i class="blue-font">点击上传</i>
          </span>
        </div>
      </div>
    </div>
  </el-upload>
  <el-dialog v-model="dialogVisible">
    <img class="w-full" :src="valuePri" alt="Preview Image" />
  </el-dialog>
</div>
</template>

<script lang="ts">
import { defineComponent, ref, watch, onMounted } from 'vue'
import { useStore } from 'vuex'
import type { UploadProps, UploadRawFile } from 'element-plus'
import { ElMessage } from 'element-plus'
import { ImageManage } from '@/services/uploadImg'
import { imageTempPreviewUrl, commonImageCompress } from '@/utils/utils'

export default defineComponent({
  name: 'ifUpload',
  props: {
    tips: {
      type: String,
      default() {
        return ''
      }
    },
    limitSize: {
      type: Number,
      default() {
        return 1024
      }
    },
    disabledStr: {
      type: Boolean,
      default() {
        return true
      }
    },
    disabled: {
      type: Boolean,
      default() {
        return false
      }
    },
    value: {
      type: String,
      default() {
        return ''
      }
    },
    isPreview: {},
  },
  components: {
  },
  data() {
    return {
      api: ImageManage.uploadImg()
    }
  },
  setup(props: any, context) {
    const api = ref<string>('')
    const store = useStore()
    const headers = ref<Record<string, any>>()
    const dialogVisible = ref<boolean>(false)
    const upload = ref()
    headers.value = {
      appId: store.state.appId,
      enterpriseId: store.state.enterpriseId,
      departmentId: store.state.departmentId,
      openId: store.state.openId,
      Authorization: store.state.accessToken ? `Bearer ${store.state.accessToken}` : ''
    }
    const valuePri = ref<string>()
    const disabledStrPri = ref<boolean>()
    const uploading = ref<boolean>(false)
    // 上传之前
    const beforeAvatarUpload = async (file: any) => {
      uploading.value = true // loading 起
      api.value = ImageManage.uploadImg()
      // 1. 先判断格式 可用accept參數限制圖片類型, 也会有一些其他的问题
      const isJPG = file.type === 'image/jpeg' || file.type === 'image/jpg'
      const isPNG = file.type === 'image/png'
      const isBMP = file.type === 'image/bmp'
      const isPass = isJPG || isPNG || isBMP
      if (!isPass) {
        uploading.value = false // loading 降
        ElMessage.error(`${props?.tips} !`)
        return false
      }
      // 2. 再判断大小
      const isNoOverSize: boolean = file.size / 1024 / 1024 < props?.limitSize
      if (!isNoOverSize) {
        ElMessage.error(`上传图片大小不能超过 ${props?.limitSize} M!`)
        uploading.value = false // loading 降
        return false
      }
      uploading.value = false // loading 降
      // 3. 内部压缩图片
      const beforeFn = (img:any, resolve:any, reject:any):boolean => {
        const { width, height } = img
        file.width = width // 获取到width放在了file属性上
        file.height = height // 获取到height放在了file属性上
        // 3.1 进行百度图片的边界判断 最短边至少15px，最长边最大4096px
        let valid = width > 15 && width < 4096
        valid = valid && (height > 15 && height < 4096)
        if (!valid) {
          ElMessage.error('百度OCR要求图片宽高在15px~4096px之间!')
          reject(file)
          return true
        }
        const isLt300KB = file.size / 1024 / 1024 < 0.3 // 判定图片大小是否大于300kb
        // 超过300kb的都压缩
        if (isLt300KB) {
          resolve(file)
          return true
        }
        return false
      }
      return commonImageCompress(file, beforeFn)
    }
    // 上传成功
    const handlePicUploadSuccess = async (res: any, file:any, files:any) => {
      if (res.code === 200) {
        ElMessage.success('图片上传成功')
        valuePri.value = await imageTempPreviewUrl(res.data.fileCode)
        disabledStrPri.value = true
        context.emit('successEvent', res.data.fileCode, file, files, valuePri.value)
      }
      uploading.value = false // loading 起
    }
    // 上传失败
    const handlePicUploadError = () => {
      uploading.value = false // loading 起
    }
    watch(() => props?.value, (newVal) => {
      if (!newVal) {
        valuePri.value = ''
        disabledStrPri.value = false
        return
      }
      valuePri.value = newVal
    })
    watch(() => props?.disabledStr, (newVal) => {
      disabledStrPri.value = newVal
    })
    const uploadFile = ref<any>()
    const hoverAvatarClick = (e:PointerEvent) => {
      e.stopPropagation() // 防止点击穿透
    }
    const handlePictureCardPreview = (e:PointerEvent) => {
      e.stopPropagation() // 防止点击穿透
      dialogVisible.value = true
      // 基于临时token来获取预览结果 // valuePri.value = uploadFile.url!
    }
    const handlePictureCardDelete = (e:PointerEvent) => {
      e.stopPropagation() // 防止点击穿透
      uploadFile.value!.clearFiles()
      disabledStrPri.value = false
      context.emit('delelteEvent', '')
      valuePri.value = ''
    }
    const handleExceed: UploadProps['onExceed'] = (files:any) => {
      upload.value!.clearFiles()
      const file = files[0] as UploadRawFile
      upload.value!.handleStart(file)
    }
    onMounted(() => {
      valuePri.value = props?.value
      disabledStrPri.value = props?.disabledStr
    })
    return {
      headers,
      valuePri,
      dialogVisible,
      upload,
      uploadFile,
      disabledStrPri,
      uploading,
      // methods
      handlePicUploadSuccess,
      beforeAvatarUpload,
      hoverAvatarClick,
      handlePictureCardPreview,
      handleExceed,
      handlePictureCardDelete,
      handlePicUploadError,
    }
  },
})

</script>
<style lang="less">
.avatar-uploader {
  width: 286px;
  height: 146px;
}
.avatar-uploader .el-upload {
    border: 1px solid #d9d9d9;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    height: 100%;
    .el-upload-dragger {
      padding: 0;
      height: 100%;
    }
    .is-drag {
      height: 100%;
    }
    .avatar-wrap {
      position: relative;
      &:hover {
        .hover-avatar {
          display: flex;
        }
      }
      &:active {
        .hover-avatar {
          display: flex;
        }
      }
    }
    .hover-avatar {
      position: absolute;
      display: none;
      width: 100%;
      height: 100%;
      left: 0;
      top: 0;
      background: rgba(0, 0, 0, 0.4);
      justify-content: center;
      align-items: center;
      .preview {
        color: #fff;
        font-size: 20px;
        margin-right: 20px;
        width: 20px;
        height: 20px;
        display: inline-block;
      }
      .delete {
        color: #fff;
        font-size: 20px;
        margin-right: 20px;
        width: 20px;
        height: 20px;
        display: inline-block;
      }
    }
}
.avatar-uploader .el-upload:hover {
    border-color: #42c57a;
}
.avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 100%;
    height: 146px;
    text-align: center;
    font-size: 16px;
    font-family: PingFangSC-Regular, PingFang SC;
    font-weight: 400;
    color: rgba(0,0,0,0.2500);
    display: flex;
    align-items: center;
    justify-content: center;
    .up-icon {
      display: flex;
      flex-direction: column;
    }
    i {
      font-style: normal;
    }
    .blue-font {
      color: #3D6CF7;
    }
    .el-icon {
      margin-bottom: 8px;
      font-size: 40px;
      color: #F3F3F3;
    }
}
.avatar {
    height: 100%;
    display: block;
    .avatar-img {
      width: 100%;
      height: 100%;
      background: no-repeat center;
      background-size: contain;
    }
}
.w-full {
  width: 100%;
}
.el-dialog__header {
  border-bottom: none;
}
</style>
